#include <at.h>
#include <hi_at.h>
#include <hi_net_api.h>
#include <hi_io.h>
#include <iot_uart.h>
#include <securec.h>
#include <stdlib.h>
#include <string.h>
#include <wifi_device.h>
#include "DataBase/DataBase.h"
#include "WIFI/WIFI.h"
#include "los_typedef.h"

#define AT_FUNC_NUM (sizeof(g_func_tbl) / sizeof(at_cmd_func))

static hi_u32 at_set_wifi_help(hi_s32 argc, const hi_char **argv)
{
    (void) argc;
    (void) argv;
    hi_at_printf("connect to WIFI and save config.\r\n"
                 "\tAT+SETWIFI=\"<ssid>\"[,auth_type[,\"key\"]]\r\n"
                 "\r\n"
                 "The password can be omitted only when auth_type is OPEN\r\n"
                 "\r\n"
                 "\tauth_type:\r\n"
                 "\t\t0 : OPEN\r\n"
                 "\t\t1 : WEP\r\n"
                 "\t\t2 : PSK\r\n"
                 "\t\t3 : SAE\r\n");
    return HI_ERR_SUCCESS;
}

static hi_u32 at_set_wifi(hi_s32 argc, const hi_char **argv)
{
    char *ssid = NULL;
    char *key = NULL;
    size_t len = 0;
    WifiDeviceConfig wifi_config = {.ipType = DHCP};
    errno_t ret = EOK;

    if (argc <= 0 || argc > 3)
    {
    miss_param:
        hi_at_printf("ERROR: missing parameter\r\n");
        return HI_ERR_FAILURE;
    }

    if ((ssid = at_parse_string(argv[0], &len)) != NULL)
    {
        ret = strcpy_s(wifi_config.ssid, WIFI_MAX_SSID_LEN, ssid);
        at_free(ssid);
        if (ret != EOK)
        {
            hi_at_printf("ERROR: ssid too long\r\n");
            return HI_ERR_FAILURE;
        }
    }
    else
    {
        hi_at_printf("ERROR: Parameter error, ssid should be a string\r\n");
        return HI_ERR_FAILURE;
    }

    if (argc >= 2)
    {
        if (integer_check(argv[1]) != HI_ERR_SUCCESS || (wifi_config.securityType = atoi(argv[1])) > 3)
        {
            hi_at_printf("ERROR: Parameter error, auth_type should be a number\r\n"
                         "\t0 : OPEN\r\n"
                         "\t1 : WEP\r\n"
                         "\t2 : PSK\r\n"
                         "\t3 : SAE\r\n");
            return HI_ERR_FAILURE;
        }

        if (wifi_config.securityType != WIFI_SEC_TYPE_OPEN && argc < 3)
        {
            goto miss_param;
        }
        else
        {
            if ((key = at_parse_string(argv[2], &len)) != NULL)
            {
                ret = strcpy_s(wifi_config.preSharedKey, WIFI_MAX_KEY_LEN, key);
                at_free(key);
                if (ret != EOK)
                {
                    hi_at_printf("ERROR: key too long\r\n");
                    return HI_ERR_FAILURE;
                }
            }
            else
            {
                hi_at_printf("ERROR: Parameter error, key should be a string\r\n");
                return HI_ERR_FAILURE;
            }
        }
    }

    if (WIFI_ConnectAndSave(&wifi_config, TRUE) == WIFI_SUCCESS)
    {
        hi_at_printf("OK\r\n");
        return HI_ERR_SUCCESS;
    }
    else
    {
        return HI_ERR_FAILURE;
    }
}

static hi_u32 at_set_uart_help(hi_s32 argc, const hi_char **argv)
{
    (void) argc;
    (void) argv;
    hi_at_printf("AT+HIKUART=<baud>,<dataBits>,<stopBit>,<parity>\r\n"
                 "\tdataBits: 5, 6, 7, 8\r\n"
                 "\tstopBit: 1, 2\r\n"
                 "\tparity: 0 None, 1 ODD, 2 Even\r\n"
                 "example: AT+SETUART=115200,8,1,0\r\n");
    return HI_ERR_SUCCESS;
}

static hi_u32 at_set_uart(hi_s32 argc, const hi_char **argv)
{
    IotUartAttribute config = {.txBlock = IOT_UART_BLOCK_STATE_NONE_BLOCK, .rxBlock = IOT_UART_BLOCK_STATE_BLOCK};
    if (argc != 4)
    {
        hi_at_printf("ERROR: missing parameter\r\n");
        return HI_ERR_FAILURE;
    }

    for (int i = 0; i < 4; i++)
    {
        if (integer_check(argv[i]) != HI_ERR_SUCCESS)
        {
            hi_at_printf("ERROR: Parameter error, should be a number\r\n");
            return HI_ERR_FAILURE;
        }
        else
        {
            int val = atoi(argv[i]);
            switch (i)
            {
            case 0:
                if (val < 0)
                {
                    hi_at_printf("ERROR: baudRate error\r\n");
                    return HI_ERR_FAILURE;
                }
                config.baudRate = val;
                break;
            case 1:
                if (val >= 5 && val <= 8)
                {
                    config.dataBits = val;
                }
                else
                {
                    hi_at_printf("ERROR: dataBits error\r\n");
                    return HI_ERR_FAILURE;
                }
                break;
            case 2:
                if (val == 1 || val == 2)
                {
                    config.stopBits = val;
                }
                else
                {
                    hi_at_printf("ERROR: stopBit error\r\n");
                    return HI_ERR_FAILURE;
                }
                break;
            case 3:
                if (val == 0 || val == 1 || val == 2)
                {
                    config.parity = val;
                }
                else
                {
                    hi_at_printf("ERROR: parity error\r\n");
                    return HI_ERR_FAILURE;
                }
                break;
            }
        }
    }

    if (db_save_uart_config(&config) == 0)
    {
        hi_at_printf("OK, Effective after restart.\r\n");
    }
    else
    {
        hi_at_printf("ERROR: IoTUartInit failure\r\n");
    }

    return HI_ERR_SUCCESS;
}

const at_cmd_func g_func_tbl[] = {
    {"+SETWIFI", 8, at_set_wifi_help, at_set_wifi_help, at_set_wifi, at_set_wifi_help},
    {"+SETUSART", 9, at_set_uart_help, at_set_uart_help, at_set_uart, at_set_uart_help},
};

void AT_custom_init(void)
{
    hi_at_register_cmd(g_func_tbl, AT_FUNC_NUM);
}